﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Reflection;

using CreativeMinds.DNSAPI.Core.Configuration;
using log4net;

namespace CreativeMinds.DNSAPI.Core {

	public static class DNSAPIFactory {

		public static DNSAPIBase GetDNSAPI(ILog log) {
			String[] parts = FactoryConfigurationSection.Settings.APIType.Split(new Char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
			if (parts.Length != 2) {
				// TODO:
				throw new ApplicationException();
			}

			Assembly assembly = Assembly.Load(parts[1]);
			Type type = assembly.GetType(parts[0]);

			List<Object> arguments = new List<object>();

			String configName = FactoryConfigurationSection.Settings.ConfigurationSection;
			if (!String.IsNullOrWhiteSpace(configName)) {
				Object config = ConfigurationManager.GetSection(configName);
				IEnumerable<PropertyInfo> properties = config.GetType().GetProperties().Where(p => p.GetCustomAttributes(typeof(ConfigurationPropertyAttribute), false).Any());

				if (properties.Count() > 0) {
					ConstructorInfo[] constructors = type.GetConstructors();
					if (constructors.Count() > 1) {
						// TODO
						throw new ApplicationException("can not handle multiple constructors");
					}
					foreach (ConstructorInfo info in constructors) {
						ParameterInfo[] parameters = info.GetParameters();
						foreach (ParameterInfo pInfo in parameters) {
							if (pInfo.Name == "log") {
								arguments.Add(log);
							}
							else {
								IEnumerable<PropertyInfo> prop = properties.Where(p => p.Name.ToLower() == pInfo.Name.ToLower());
								if (prop.Any()) {
									arguments.Add(prop.First().GetValue(config, null));
								}
								else {
									throw new ApplicationException("missing parameter " + pInfo.Name);
								}
							}
						}
					}
				}
			}

			// TODO: Arguments for the constructor!
			return (DNSAPIBase)Activator.CreateInstance(type, arguments.ToArray());
		}
	}
}